package com.dayu.finecomm.protocol.pojo;

import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName: TPacket
 * @Description:报文
 * @author: 戴卫国
 * @date: 2018年2月23日 下午4:18:01
 * 
 * @Copyright: 2018 dayu Inc. All rights reserved.
 */
public class TPacket {

	public static enum VType {

		RRR(0), PPP(1), MMM(2), YCB(3), OPC(4);

		int val;

		private VType(int type) {
			this.val = type;
		}

		public int value() {
			return val;
		}

		@Override
		public String toString() {
			return Integer.toString(val);
		}
	}

	public String prefix;
	public String protocol;
	public VType type;
	public String sn;
	public Long timestamp;
	public Long created;

	public String batchno;
	public String cbType;
	public String end;

	public String appId;

	/**
	 * 客户编码（效率机上用）
	 * 
	 * @Fields imei : TODO
	 */
	public String imei;

	public TCommand command;

	public List<TPacket> packets = new ArrayList<>();

	public LinkedList<TSensor> sensors;

	public InetSocketAddress address;

	public String result;

	// 源报文
	public String in;

	public TPacket() {
		this(VType.RRR, "", "", null);
	}

	public TPacket(VType type) {

		this(type, "", "", null);
	}

	public TPacket(VType type, String protocol, long sn) {

		this(type, protocol, Long.toString(sn), null);
	}

	public TPacket(VType type, String protocol, String sn) {

		this(type, protocol, sn, null);
	}

	public TPacket(VType type, String protocol, long sn, Long timestamp) {

		this(type, protocol, Long.toString(sn), timestamp);
	}

	public TPacket(VType type, String protocol, String sn, Long timestamp) {

		this.type = type;
		this.protocol = protocol;
		this.sn = sn;
		this.timestamp = timestamp;

		this.created = System.currentTimeMillis();

		sensors = new LinkedList<>();
	}

	public String id() {

		StringBuilder sb = new StringBuilder();

		if (!("".equals(prefix) || prefix == null)) {
			sb.append(prefix);
		}

		if (!("".equals(protocol) || protocol == null)) {
			if (sb.length() > 0) {
				sb.append("_");
			}
			sb.append(protocol);
		}

		if (!("".equals(imei) || imei == null)) {
			if (sb.length() > 0) {
				sb.append("_");
			}
			sb.append(imei);
		}

		if (!("".equals(sn) || sn == null)) {
			if (sb.length() > 0) {
				sb.append("_");
			}
			sb.append(sn);
		}

		return sb.toString();
	}

	public TSensor first(String channel) {

		TSensor[] items = items(channel);
		return (items == null || items.length == 0) ? null : items[0];
	}

	public TSensor last(String channel) {

		TSensor[] items = items(channel);
		return (items == null || items.length == 0) ? null : items[items.length - 1];
	}

	public TSensor[] items(String channel) {

		List<TSensor> sensors = new ArrayList<>();

		for (TSensor s : this.sensors) {
			if (s.channel.equals(channel)) {
				sensors.add(s);
			}
		}

		return sensors.toArray(new TSensor[0]);
	}

	public TSensor[] remove(String channel) {

		List<TSensor> sensors = new ArrayList<>();

		Iterator<TSensor> iterator = this.sensors.iterator();

		while (iterator.hasNext()) {

			TSensor s = iterator.next();
			if (s.channel.equals(channel)) {

				sensors.add(s);
				iterator.remove();
			}
		}

		return sensors.toArray(new TSensor[0]);
	}

	@Override
	public String toString() {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		StringBuilder sb = new StringBuilder();
		sb.append(this.type.name());

		if (this.type.name().equals(VType.YCB.name()) && batchno != null && cbType != null && end != null) {
			sb.append("_");
			sb.append(batchno);
			sb.append("_");
			sb.append(cbType);
			sb.append("_");
			sb.append(end);
		}

		if (null != appId && !appId.isEmpty()) {
			sb.append("_");
			sb.append(appId);
		}

		sb.append('{');

		boolean first = true;

		for (TSensor s : sensors) {

			Long ts = s.timestamp;

			if (ts == null) {
				ts = this.timestamp;
			}

			if (ts == null)
				continue;

			if (!first)
				sb.append('|');
			else
				first = false;

			String id = id();

			if ("".equals(id) || id == null) {
			} else {
				sb.append(id);
				sb.append("_");
			}

			sb.append(s.channel);
			sb.append('|');

			if (s.val instanceof Double || s.val instanceof Float) {
				sb.append(String.format("%.6f", s.val));
			} else {
				sb.append(s.val);
			}

			sb.append('|');
			sb.append(sdf.format(new Date(ts)));
		}

		sb.append('}');

		return sb.toString();
	}
}
